home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / util / misc / adpcm_pa.lha / FP_ADPCM / PlayADPCM / Source / PlayADPCM.c < prev   
C/C++ Source or Header  |  1995-04-27  |  13KB  |  571 lines

  1.  
  2. /*        Stand-Alone Player for ADPCM audio samples            */
  3. /* Written in 1995 by Christian Buchner. This is Public Domain. */
  4. /* Also look out for xPlay, also available on AmiNet */
  5.  
  6. /* Note: TAB SIZE = 4 */
  7.  
  8. /* History:
  9.  
  10.    V1.1: Now recognizes when channels have been stolen
  11.          Uses WaitIO() instead of WaitPort()/GetMsg() pair.
  12. */
  13.  
  14. /* Includes */
  15.  
  16. #include <clib/dos_protos.h>
  17. #include <clib/exec_protos.h>
  18. #include <clib/alib_protos.h>
  19. #include <pragmas/dos_pragmas.h>
  20. #include <pragmas/exec_pragmas.h>
  21.  
  22. #include <libraries/dos.h>
  23. #include <dos/rdargs.h>
  24. #include <utility/tagitem.h>
  25. #include <devices/audio.h>
  26. #include <exec/execbase.h>
  27. #include <exec/memory.h>
  28. #include <string.h>
  29. #include <hardware/cia.h>
  30.  
  31.  
  32. /* Version string */
  33.  
  34. UBYTE Version[]="$VER: PlayADPCM 1.1 "__AMIGADATE__" by Christian Buchner";
  35.  
  36.  
  37. /* Prototypes */
  38.  
  39. BOOL PlayADPCM(struct MyVars *mv, UBYTE *Filename, ULONG Size, ULONG Filter, ULONG NoFilter, ULONG Quiet);
  40. BOOL OpenAudio(struct MyVars *mv, ULONG Filter, ULONG NoFilter);
  41. void CloseAudio(struct MyVars *mv);
  42. void AbortPlay(struct MyVars *mv);
  43. void WaitPlay(struct MyVars *mv);
  44.  
  45.  
  46. extern __asm ULONG DecompressADPCM2(    register __a0 UBYTE *Source,
  47.                                         register __d0 ULONG Length,
  48.                                         register __a1 UBYTE *Destination,
  49.                                         register __d1 ULONG JoinCode    );
  50.  
  51. extern __asm ULONG DecompressADPCM3(    register __a0 UBYTE *Source,
  52.                                         register __d0 ULONG Length,
  53.                                         register __a1 UBYTE *Destination,
  54.                                         register __d1 ULONG JoinCode    );
  55.  
  56.  
  57. /* Replay Buffer size */
  58.  
  59. #define CHIP_SIZE 16384
  60.  
  61.  
  62. /* CLI Arguments */
  63.  
  64. UBYTE Template[]="FILES/M/A,ALL/S,FL=FILTER/S,NFL=NOFILTER/S,QUIET/S";
  65.  
  66. struct ArgArray
  67. {
  68.     UBYTE **aa_Files;
  69.     ULONG aa_All;
  70.     ULONG aa_Filter;
  71.     ULONG aa_NoFilter;
  72.     ULONG aa_Quiet;
  73. };
  74.  
  75.  
  76. /* Library Bases */
  77.  
  78. struct DosLibrary *DOSBase;
  79.  
  80.  
  81. /* Local Variables */
  82.  
  83. struct MyVars
  84. {
  85.     struct Process *MyProc;
  86.     
  87.     struct MsgPort *LeftReply[2];
  88.     struct MsgPort *RightReply[2];
  89.     struct IOAudio *LeftAudio[2];
  90.     struct IOAudio *RightAudio[2];
  91.     
  92.     BOOL Playing;
  93.     
  94.     UBYTE *ChipBuffer[2];
  95.     
  96.     BOOL BufPlaying[2];
  97. };
  98.  
  99.  
  100. /* Access to CIA registers */
  101.  
  102. struct CIA *ciaa=(struct CIA*)0xbfe001;
  103.  
  104.  
  105. /* CLI interface and Pattern Matching */
  106.  
  107. LONG __saveds main(void)
  108. {
  109.     struct MyVars *mv;
  110.     UBYTE ProgName[60];
  111.     struct RDArgs *RDArgs;
  112.     struct ArgArray AA={NULL,FALSE,FALSE,FALSE,FALSE};
  113.     char **Files;
  114.     struct AnchorPath *AnchorPath;
  115.     ULONG ReturnCode=RETURN_FAIL;
  116.     
  117.     if (mv=AllocVec(sizeof(struct MyVars),MEMF_ANY|MEMF_CLEAR))
  118.     {
  119.         if (DOSBase=(struct DosLibrary*)OpenLibrary("dos.library",37))
  120.         {
  121.             if (!GetProgramName(ProgName,sizeof(ProgName))) strcpy(ProgName,"PlayADPCM");
  122.             
  123.             if (!(RDArgs=ReadArgs(Template,(LONG *)&AA,0)))
  124.             {
  125.                 PrintFault(IoErr(),ProgName);
  126.             }
  127.             else
  128.             {
  129.                 if (Files=AA.aa_Files)
  130.                 {
  131.                     if (!(AnchorPath=(struct AnchorPath *)AllocVec(sizeof(struct AnchorPath)+256,MEMF_PUBLIC|MEMF_CLEAR)))
  132.                     {
  133.                         PrintFault(ERROR_NO_FREE_STORE,ProgName);
  134.                     }
  135.                     else
  136.                     {
  137.                         ReturnCode=RETURN_OK;
  138.                         
  139.                         AnchorPath->ap_BreakBits=SIGBREAKF_CTRL_C;
  140.                         AnchorPath->ap_Strlen=256;
  141.                         
  142.                         while ((!ReturnCode) && *Files)
  143.                         {
  144.                             LONG RetVal;
  145.                             
  146.                             RetVal=MatchFirst(*Files,AnchorPath);
  147.                             while(!RetVal)
  148.                             {
  149.                                 if (AnchorPath->ap_Info.fib_DirEntryType>0L)
  150.                                 {
  151.                                     if ((!(AnchorPath->ap_Flags&APF_DIDDIR))&&AA.aa_All)
  152.                                     {
  153.                                         AnchorPath->ap_Flags|=APF_DODIR;
  154.                                     }
  155.                                     AnchorPath->ap_Flags&=~APF_DIDDIR;
  156.                                 }
  157.                                 else
  158.                                 {
  159.                                     if (PlayADPCM(mv, AnchorPath->ap_Buf, AnchorPath->ap_Info.fib_Size, AA.aa_Filter, AA.aa_NoFilter, AA.aa_Quiet))
  160.                                     {
  161.                                         RetVal=ERROR_BREAK;
  162.                                         break;
  163.                                     }
  164.                                 }
  165.                                 RetVal=MatchNext(AnchorPath);
  166.                             }
  167.                             MatchEnd(AnchorPath);
  168.                             
  169.                             if (RetVal==ERROR_BREAK)
  170.                             {
  171.                                 PrintFault(RetVal,NULL);
  172.                                 ReturnCode=RETURN_WARN;
  173.                             }
  174.                             else
  175.                             {
  176.                                 if (RetVal!=ERROR_NO_MORE_ENTRIES)
  177.                                 {
  178.                                     PrintFault(RetVal,*Files);
  179.                                     ReturnCode=RETURN_ERROR;
  180.                                 }
  181.                             }
  182.                             Files++;
  183.                         }
  184.                         FreeVec((APTR)AnchorPath);
  185.                     }
  186.                 }
  187.                 FreeArgs(RDArgs);
  188.             }
  189.             CloseLibrary((struct Library*)DOSBase);
  190.         }
  191.         FreeVec(mv);
  192.     }
  193. }
  194.  
  195.  
  196. /* The primitive sample header */
  197.  
  198. struct ADPCMHeader
  199. {
  200.     UBYTE Identifier[6];
  201.     ULONG Frequency;
  202. };
  203.  
  204.  
  205. /* The playback routine */
  206.  
  207. BOOL PlayADPCM(struct MyVars *mv, UBYTE *Filename, ULONG Size, ULONG Filter, ULONG NoFilter, ULONG Quiet)
  208. {
  209.     BOOL Break=FALSE;
  210.     
  211.     BPTR File;
  212.     struct ADPCMHeader ADPCMHeader;
  213.     
  214.     if (!(File=Open(Filename,MODE_OLDFILE)))
  215.     {
  216.         PrintFault(IoErr(),Filename);
  217.     }
  218.     else
  219.     {
  220.         /* Read in sample header */
  221.         if (Read(File,&ADPCMHeader,sizeof(struct ADPCMHeader))==sizeof(struct ADPCMHeader))
  222.         {
  223.             if (strncmp("ADPCM",ADPCMHeader.Identifier,5))
  224.             {
  225.                 Printf("%s: Not ADPCM format!\n",Filename);
  226.             }
  227.             else
  228.             {
  229.                 Size-=sizeof(ADPCMHeader);
  230.                 
  231.                 /* Check if it is a supported ADPCM format */
  232.                 if (ADPCMHeader.Identifier[5] != '2' && ADPCMHeader.Identifier[5] != '3')
  233.                 {
  234.                     Printf("%s: Unsupported ADPCM format!\n",Filename);
  235.                 }
  236.                 else
  237.                 {
  238.                     ULONG Bits;
  239.                     
  240.                     /* Retrieve the number of compression bits */
  241.                     if (ADPCMHeader.Identifier[5] == '2') Bits=2;
  242.                     if (ADPCMHeader.Identifier[5] == '3') Bits=3;
  243.                     
  244.                     if (!OpenAudio(mv,Filter,NoFilter))
  245.                     {
  246.                         Printf("%s: Can't get audio channels!\n",Filename);
  247.                     }
  248.                     else
  249.                     {
  250.                         UBYTE *ADPCMBuffer;
  251.                         ULONG ADPCMSize;
  252.                         
  253.                         if (Bits==2) ADPCMSize=(CHIP_SIZE+3)/4;
  254.                         if (Bits==3) ADPCMSize=(CHIP_SIZE+7)/8*3;
  255.                         
  256.                         if (!(ADPCMBuffer=AllocVec(ADPCMSize, MEMF_ANY|MEMF_CLEAR)))
  257.                         {
  258.                             Printf("%s: Out of memory!\n",Filename);
  259.                         }
  260.                         else
  261.                         {
  262.                             struct Process *MyProc;
  263.                             ULONG Position=0;
  264.                             ULONG JoinCode=0;
  265.                             BOOL ProcActive=TRUE;
  266.                             ULONG Signals;
  267.                             UWORD i;
  268.                             LONG ChipMax, Left, Do, DMALen;
  269.                             BOOL Aborted=FALSE;
  270.                             
  271.                             if (!Quiet) Printf("\rPlaying %s",Filename);
  272.                             
  273.                             MyProc=(struct Process*)FindTask(NULL);
  274.                             
  275.                             Signal(MyProc,(1L<<mv->LeftReply[0]->mp_SigBit));
  276.                             Signal(MyProc,(1L<<mv->LeftReply[1]->mp_SigBit));
  277.                             
  278.                             while(ProcActive)
  279.                             {
  280.                                 ULONG SigMask = SIGBREAKF_CTRL_C |
  281.                                                 (1L<<mv->LeftReply[0]->mp_SigBit) | 
  282.                                                 (1L<<mv->LeftReply[1]->mp_SigBit) ;
  283.                                 
  284.                                 Signals=Wait(SigMask);
  285.                                 
  286.                                 if (Signals & SIGBREAKF_CTRL_C)
  287.                                 {
  288.                                     Printf("\n");
  289.                                     
  290.                                     AbortPlay(mv);
  291.                                     
  292.                                     Break=TRUE;
  293.                                     Aborted=TRUE;
  294.                                     ProcActive=FALSE;
  295.                                 }
  296.                                 
  297.                                 for (i=0;ProcActive && i<2;i++)
  298.                                 {
  299.                                     if (Signals & (1L<<mv->LeftReply[i]->mp_SigBit))
  300.                                     {
  301.                                         if (mv->BufPlaying[i])
  302.                                         {
  303.                                             BYTE LError, RError;
  304.                                             
  305.                                             LError=WaitIO(mv->LeftAudio[i]);
  306.                                             RError=WaitIO(mv->RightAudio[i]);
  307.                                             mv->BufPlaying[i]=FALSE;
  308.                                             
  309.                                             if (LError || RError)
  310.                                             {
  311.                                                 Printf("\r%s: Channels have been stolen!\n",Filename);
  312.                                                 
  313.                                                 AbortPlay(mv);
  314.                                                 
  315.                                                 Aborted=TRUE;
  316.                                                 ProcActive=FALSE;
  317.                                                 break;
  318.                                             }
  319.                                         }
  320.                                         
  321.                                         if (Bits==2) ChipMax = (CHIP_SIZE+3)/4;
  322.                                         if (Bits==3) ChipMax = (CHIP_SIZE+7)/8*3;
  323.                                         
  324.                                         if (Position>=Size)
  325.                                         {
  326.                                             Position=0;
  327.                                             
  328.                                             ProcActive=FALSE;
  329.                                             break;
  330.                                         }
  331.                                         
  332.                                         Left = Size-Position;
  333.                                         Do = Left < ChipMax ? Left : ChipMax;
  334.                                         
  335.                                         if (Do>0)
  336.                                         {
  337.                                             LONG Got;
  338.                                             
  339.                                             if (!Quiet) Printf("\rPlaying %s (%02ld%%)",Filename,100*Position/Size);
  340.                                             
  341.                                             if (Got=Read(File, ADPCMBuffer, Do) != Do)
  342.                                             {
  343.                                                 if (Got<0) PrintFault(IoErr(),Filename);
  344.                                                 else Printf("\r%s: Error, short read!\n",Filename);
  345.                                                 Aborted=TRUE;
  346.                                                 ProcActive=FALSE;
  347.                                                 break;
  348.                                             }
  349.                                             
  350.                                             if (Bits==2) JoinCode=DecompressADPCM2(ADPCMBuffer, Do, mv->ChipBuffer[i], JoinCode);
  351.                                             if (Bits==3) JoinCode=DecompressADPCM3(ADPCMBuffer, Do, mv->ChipBuffer[i], JoinCode);
  352.                                             
  353.                                             Position+=Do;
  354.                                             
  355.                                             if (Bits==2) DMALen = Do*4;
  356.                                             if (Bits==3) DMALen = Do*8/3;
  357.                                             
  358.                                             mv->LeftAudio[i]->ioa_Data =
  359.                                             mv->RightAudio[i]->ioa_Data = mv->ChipBuffer[i];
  360.                                             
  361.                                             mv->LeftAudio[i]->ioa_Length =
  362.                                             mv->RightAudio[i]->ioa_Length = DMALen;
  363.                                             
  364.                                             mv->LeftAudio[i]->ioa_Period = 
  365.                                             mv->RightAudio[i]->ioa_Period=(*(struct ExecBase**)(4))->ex_EClockFrequency*5/ADPCMHeader.Frequency;
  366.                                             
  367.                                             mv->LeftAudio[i]->ioa_Volume=64;
  368.                                             mv->RightAudio[i]->ioa_Volume=64;
  369.                                             
  370.                                             mv->LeftAudio[i]->ioa_Cycles=
  371.                                             mv->RightAudio[i]->ioa_Cycles=1;
  372.                                             
  373.                                             mv->LeftAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  374.                                             mv->RightAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  375.                                             
  376.                                             mv->LeftAudio[i]->ioa_Request.io_Command=
  377.                                             mv->RightAudio[i]->ioa_Request.io_Command=CMD_WRITE;
  378.                                             
  379.                                             Forbid();
  380.                                             BeginIO(mv->LeftAudio[i]);
  381.                                             BeginIO(mv->RightAudio[i]);
  382.                                             mv->BufPlaying[i]=TRUE;
  383.                                             Permit();
  384.                                         }
  385.                                     }
  386.                                 }
  387.                             }
  388.                             
  389.                             WaitPlay(mv);
  390.                             
  391.                             if ((!Quiet) && (!Aborted)) Printf("\rPlayed  %s - OK \n",Filename);
  392.                             
  393.                             FreeVec(ADPCMBuffer);
  394.                         }
  395.                         CloseAudio(mv);
  396.                     }
  397.                 }
  398.             }
  399.         }
  400.         Close(File);
  401.     }
  402.     return(Break);
  403. }
  404.  
  405.  
  406. /* Allocate audio channels */
  407.  
  408. BOOL OpenAudio(struct MyVars *mv, ULONG Filter, ULONG NoFilter)
  409. {
  410.     BOOL Success=FALSE;
  411.     UWORD i;
  412.     
  413.     UBYTE LeftArray[2]={1,8};
  414.     UBYTE RightArray[2]={2,4};
  415.     
  416.     for (i=0;i<2;i++)
  417.     {
  418.         if (!(mv->LeftReply[i]=CreateMsgPort())) break;
  419.         if (!(mv->RightReply[i]=CreateMsgPort())) break;
  420.         
  421.         if (!(mv->LeftAudio[i]=CreateIORequest(mv->LeftReply[i],sizeof(struct IOAudio)))) break;
  422.         if (!(mv->RightAudio[i]=CreateIORequest(mv->RightReply[i],sizeof(struct IOAudio)))) break;
  423.         
  424.         if (!(mv->ChipBuffer[i]=AllocVec(CHIP_SIZE,MEMF_CHIP))) break;
  425.     }
  426.     if (i==2)
  427.     {
  428.         mv->LeftAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=0;
  429.         mv->LeftAudio[0]->ioa_Length=sizeof(LeftArray);
  430.         mv->LeftAudio[0]->ioa_Data=LeftArray;
  431.         mv->LeftAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  432.         if (!OpenDevice("audio.device",0L,(struct IORequest *)mv->LeftAudio[0],0))
  433.         {
  434.             mv->LeftAudio[1]->ioa_Request.io_Device=mv->LeftAudio[0]->ioa_Request.io_Device;
  435.             mv->LeftAudio[1]->ioa_Request.io_Unit=mv->LeftAudio[0]->ioa_Request.io_Unit;
  436.             mv->LeftAudio[1]->ioa_AllocKey=mv->LeftAudio[0]->ioa_AllocKey;
  437.             
  438.             mv->RightAudio[0]->ioa_Length=sizeof(RightArray);
  439.             mv->RightAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=0;
  440.             mv->RightAudio[0]->ioa_Data=RightArray;
  441.             mv->RightAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  442.             if (!OpenDevice("audio.device",0L,(struct IORequest *)mv->RightAudio[0],0))
  443.             {
  444.                 mv->RightAudio[1]->ioa_Request.io_Device=mv->RightAudio[0]->ioa_Request.io_Device;
  445.                 mv->RightAudio[1]->ioa_Request.io_Unit=mv->RightAudio[0]->ioa_Request.io_Unit;
  446.                 mv->RightAudio[1]->ioa_AllocKey=mv->RightAudio[0]->ioa_AllocKey;
  447.                 
  448.                 mv->BufPlaying[0]=mv->BufPlaying[1]=FALSE;
  449.                 
  450.                 if (Filter)
  451.                 {
  452.                     ciaa->ciapra &= ~(CIAF_LED);
  453.                 }
  454.                 if (NoFilter)
  455.                 {
  456.                     ciaa->ciapra |= CIAF_LED;
  457.                 }
  458.                 
  459.                 Success=TRUE;
  460.             }
  461.         }
  462.     }
  463.     
  464.     if (!Success)
  465.     {
  466.         CloseAudio(mv);
  467.     }
  468.     
  469.     return(Success);
  470. }
  471.  
  472.  
  473. /* Abort playing */
  474.  
  475. void AbortPlay(struct MyVars *mv)
  476. {
  477.     WORD i;
  478.     
  479.     for (i=0;i<2;i++)
  480.     {
  481.         if (mv->BufPlaying[i])
  482.         {
  483.             AbortIO(mv->LeftAudio[i]);
  484.             AbortIO(mv->RightAudio[i]);
  485.         }
  486.     }
  487.     
  488.     WaitPlay(mv);
  489. }
  490.  
  491.  
  492. /* Wait for audio requests */
  493.  
  494. void WaitPlay(struct MyVars *mv)
  495. {
  496.     WORD i;
  497.     
  498.     for (i=0;i<2;i++)
  499.     {
  500.         if (mv->BufPlaying[i])
  501.         {
  502.             WaitIO(mv->LeftAudio[i]);
  503.             WaitIO(mv->RightAudio[i]);
  504.             mv->BufPlaying[i]=FALSE;
  505.         }
  506.     }
  507. }
  508.  
  509.  
  510. /* Close the audio channels */
  511.  
  512. void CloseAudio(struct MyVars *mv)
  513. {
  514.     WORD i;
  515.     
  516.     for (i=0;i<2;i++)
  517.     {
  518.         if (mv->BufPlaying[i])
  519.         {
  520.             AbortIO(mv->LeftAudio[i]);
  521.             AbortIO(mv->RightAudio[i]);
  522.             WaitIO(mv->LeftAudio[i]);
  523.             WaitIO(mv->RightAudio[i]);
  524.             mv->BufPlaying[i]=FALSE;
  525.         }
  526.     }
  527.     
  528.     for (i=1;i>=0;i--)
  529.     {
  530.         if (mv->ChipBuffer[i])
  531.         {
  532.             FreeVec(mv->ChipBuffer[i]);
  533.             mv->ChipBuffer[i]=NULL;
  534.         }
  535.         
  536.         if (mv->RightAudio[i])
  537.         {
  538.             if (i==0 && mv->RightAudio[i]->ioa_Request.io_Device)
  539.             {
  540.                 CloseDevice(mv->RightAudio[i]);
  541.                 mv->RightAudio[i]->ioa_Request.io_Device=NULL;
  542.             }
  543.             DeleteIORequest(mv->RightAudio[i]);
  544.             mv->RightAudio[i]=NULL;
  545.         }
  546.         
  547.         if (mv->RightReply[i])
  548.         {
  549.             DeleteMsgPort(mv->RightReply[i]);
  550.             mv->RightReply[i]=NULL;
  551.         }
  552.         
  553.         if (mv->LeftAudio[i])
  554.         {
  555.             if (i==0 && mv->LeftAudio[i]->ioa_Request.io_Device)
  556.             {
  557.                 CloseDevice(mv->LeftAudio[i]);
  558.                 mv->LeftAudio[i]->ioa_Request.io_Device=NULL;
  559.             }
  560.             DeleteIORequest(mv->LeftAudio[i]);
  561.             mv->LeftAudio[i]=NULL;
  562.         }
  563.         
  564.         if (mv->LeftReply[i])
  565.         {
  566.             DeleteMsgPort(mv->LeftReply[i]);
  567.             mv->LeftReply[i]=NULL;
  568.         }
  569.     }
  570. }
  571.